import instrucciones.Instruccion;
import instrucciones.Tipo_I;
import instrucciones.Tipo_J;
import instrucciones.Tipo_R;


public class Identificador {
//	private String linea;
	private String operacion;
	private String[] argumentos;
	private String[] parentesis;
	private String rs;
	private String rt;
	private String rd;
	private String sa;
	private String immediate;
	private String target;
	private String offset;
	private String base;

	
	public Instruccion ProcesarLinea(String linea){
		 
		String[] espacio = linea.split(" ");
		argumentos = espacio[1].split(",");
		operacion = espacio[0];
		
		Instruccion ins = Seleccionar();  /** vieja, le agregue esto porque modifique el metodo
		 										Necesito que me devuelva una instruccion para poder usar los 
		 										metodos de las instrucciones*/
		return ins;
	}
	
	public Instruccion Seleccionar(){		/** Aca en lugar de crear un objeto y asignarlo a una variable
	 											crealo y mandalo como return directamente. Los que hiciste estan todos
	 											corregidos. Faltan todos los demas*/
		
		switch (operacion) {
	         case "ADD":    
	            Tipo_R_rd_rs_rt();
	            return new Tipo_R("0",rs,rt,rd,"0", "32"); //Devuelve una Instruccion
	         case "AND":
	        	Tipo_R_rd_rs_rt();
	        	return new Tipo_R("0",rs,rt,rd,"0", "36");
	         case "NOR":    
	        	Tipo_R_rd_rs_rt();
	        	return new Tipo_R("0",rs,rt,rd,"0", "39");
		     case "OR":
		    	Tipo_R_rd_rs_rt();
		    	return new Tipo_R("0",rs,rt,rd,"0", "37");
		     case "SLL":    
		    	 Tipo_R_rd_rt_sa();
		    	 return new Tipo_R("0","0",rt,rd,sa, "0");
		     case "SLLV":
		    	 Tipo_R_rd_rt_rs();
		    	 return new Tipo_R("0",rs,rt,rd,"0", "4");
		     case "SLT":    
		    	 Tipo_R_rd_rs_rt();
		    	 return new Tipo_R("0",rs,rt,rd,"0", "42");
			 case "SRA":
				 Tipo_R_rd_rt_sa();
				 return new Tipo_R("0","0",rt,rd,sa, "3");
			 case "SRAV":    
				 Tipo_R_rd_rt_rs();
				 return new Tipo_R("0",rs,rt,rd,"0", "7");
		     case "SRL":
		    	 Tipo_R_rd_rt_sa();
		    	 return new Tipo_R("0","0",rt,rd,sa, "2");
		     case "SRLV":    
		    	 Tipo_R_rd_rt_rs();
		    	 return new Tipo_R("0",rs,rt,rd,"0", "6");
			 case "SUB":
				 Tipo_R_rd_rs_rt();
				 return new Tipo_R("0",rs,rt,rd,"0", "34");
			 case "XOR":    
				 Tipo_R_rd_rs_rt();
				 return new Tipo_R("0",rs,rt,rd,"0", "38");
			 case "JALR":
				 Tipo_R_rd_rt_rs();
				 return new Tipo_R("0",rs,"0",rd,"0", "9");		 
			 case "JR":
				 rs = argumentos[0];
				 return new Tipo_R("0",rs,"0","0","0", "8");
				
			//comienzo de instrucciones tipo J	 

			 case "J":
				 Tipo_jj();
				 return new Tipo_J("2",target);
			 case "JAL":
				 Tipo_jj();
				 return new Tipo_J("3",target);
			
			//comienzo de instrucciones tipo I
				 //Tipo_I(String opcode, String rs, String rt, String inm, String[] codigo)
			 case "LB":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("32",base,rt,offset);
			 case "LH":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("33",base,rt,offset);
			 case "LW":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("35",base,rt,offset);
			 case "LWU":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("39",base,rt,offset);
			 case "LBU":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("36",base,rt,offset);
			 case "LHU":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("37",base,rt,offset);
			 case "SB":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("40",base,rt,offset);
			 case "SH":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("41",base,rt,offset);
			 case "SW":
				 Tipo_I_rt_offset_base();
				 return new Tipo_I("43",base,rt,offset);
			 case "ADDI":
				 Tipo_I_rt_rs_immediate();
				 return new Tipo_I("8",rs,rt,immediate);
			 case "ANDI":
				 Tipo_I_rt_rs_immediate();
				 return new Tipo_I("12",rs,rt,immediate);
			 case "ORI":
				 Tipo_I_rt_rs_immediate();
				 return new Tipo_I("13",rs,rt,immediate);
			 case "XORI":
				 Tipo_I_rt_rs_immediate();
				 return new Tipo_I("14",rs,rt,immediate);
			 case "LUI":
				 Tipo_I_rt_inmediate();
				 return new Tipo_I("15","0",rt,immediate);
			 case "SLTI":
				 Tipo_I_rt_rs_immediate();
				 return new Tipo_I("10",rs,rt,immediate);
			 case "BEQ":
				 Tipo_I_rs_rt_offset();
				 return new Tipo_I("4",rs,rt,offset);
			 case "BNE":
				 Tipo_I_rs_rt_offset();
				 return new Tipo_I("5",rs,rt,offset);
			 default:
	             throw new IllegalArgumentException("Operacion invalida ");
	     }		
	}
	
	public void Tipo_R_rd_rs_rt(){

		rd = argumentos[0];
		rs = argumentos[1];
		rt = argumentos[2];

	}
	
	public void Tipo_R_rd_rt_rs(){

		rd = argumentos[0];
		rt = argumentos[1];
		rs = argumentos[2];
		
	}
	
	public void Tipo_R_rd_rt_sa(){

		rd = argumentos[0];
		rt = argumentos[1];
		sa = argumentos[2];
	}
	
	public void Tipo_jj(){
		
		target = argumentos[0];
	}
	
	public void Tipo_I_rt_offset_base(){
		rt = argumentos[0];
		parentesis = argumentos[1].split("\\("); //Separo por parentesis despues de aca me queda [offset, base)]
		offset = parentesis[0];
		parentesis = parentesis[1].split("\\)"); //Le saco el parentesis del final, me queda [base]
		base = parentesis[0];
	}
	
	public void Tipo_I_rt_rs_immediate(){
		
		rt = argumentos[0];
		rs = argumentos[1];
		immediate = argumentos[2];
	}
	
	public void Tipo_I_rt_inmediate(){
		
		rt = argumentos[0];
		immediate = argumentos[1];
	}
	
	public void Tipo_I_rs_rt_offset(){
		
		rs = argumentos[0];
		rt = argumentos[1];
		offset = argumentos[2];
	}
}
